[OpenCV] 一定期間動かないものだけを撮影する
1 はじめに
CX事業本部の平内(SIN)です。
OpenCVでは、背景差分という手法で、動くものだけを検出する作業がよく紹介されています。
今回は、店舗で商品の監視など場合などに、お客さんの伸ばした手や、人影などが、その監視にノイズとなって入ることを避けるため、「動かないもの」のみを撮影してみました。
商品のように数が増減するものは、監視の対象となりますので、背景差分のように、最初に完全な背景を設定するのではなく、前のフレームとの差分を確認しながら、「一定期間 動かないもの」を撮影するイメージです。
最初に、動作している様子を御覧ください。 左が、監視画面で、右は、普通のモニターです。手などが入ってきても、それは、無視されます。
2 差分検出
1つ前のフレームとの比較を行う場合、差分検出を単純化させるため、以下の処理としました。
- フレーム画像をグレースケールに変換する
- 2つの画像の差分画像を生成する
- 差分画像を2値化する
- 2値化した画像の白の要素(変化部分)数をカウントする
最終的にカウントされた白の要素(変化部分)数が、敷居値(threshold=1000)以下の場合は、変化がないと判断して、カウンターをインクリメントします。
カウンターが静止間隔(span=50 50フレーム 2秒弱)を超えたら、画面は静止していると判断し、監視画面を更新します。
3 コード
全てのコードは、以下のとおりです。
import cv2 # 2値化 def binarization(img, threshold=100): ret, img = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY) return img # 差分を数値化 def getDiff(img1, img2): # グレースケール変換 img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 差分取得 mask = cv2.absdiff(img1, img2) # 2値化 mask = binarization(mask) return cv2.countNonZero(mask) # 白の要素数 span = 50 # 静止間隔 threshold = 1000 # 変化の敷居値 # 動画ファイルのキャプチャ cap = cv2.VideoCapture(1) cap.set(cv2.CAP_PROP_FPS, 30) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 420) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 最初のフレームを背景画像に設定 ret, previous = cap.read() counter=0 while(cap.isOpened()): # フレームの取得 ret, frame = cap.read() # 差分計算 diff = getDiff(previous, frame) if(diff < threshold): counter+=1 else: counter=0 print("diff:{} counter:{}".format(diff,counter)) # 一定以下の変化量が、一定時間続いたら描画する if(span < counter): counter = 0 # 監視画面を更新 cv2.imshow("previous", frame) # フレームを表示 cv2.imshow("Flame", frame) # 今回のフレームを1つ前として保存する previous = frame if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
4 利用例
参考に、この「動かないものだけ撮影する」仕組みで、機械学習のモデルの精度を試している様子です。
Amazon Rekognition Custom Labelsを使用しています。私の作ったモデルは、けっして精度が良いとは言えませんが、数枚(12枚です)の写真でモデルが作成出来てしまうところが凄いと思います。
モデルの精度をテストをする場合も、できるだけ短い時間のRUNNINGで、より効果的に確認を行うためには、このようなやり方も悪くないかも知れません。
5 最後に
今更ですが、動画、画像を扱う場合、OpenCVのようなツールで必要な画像処理を加えることは、サービスを組み立てる上で必須だと思います。
何をどのように組み合わせると、どのような事ができるのか、日頃から色々確認しておく事が必要でしょう。